/*! \file p2p.h
 * \brief Wi-Fi Direct/P2P
 *
 * Wi-Fi Direct (P2P) is a standard that defines a new way for Wi-Fi devices
 * to work together. Wi-Fi devices will be able to make direct connections to
 * one another quickly and conveniently to do things like print, sync, and
 * share content even when an access point or router is unavailable.
 * Wi-Fi Direct connections will work at typical Wi-Fi speeds and range,
 * protected by WPA2 security protocols.
 *
 * Two methods that are supported by SDK are:
 *
 * \li PIN Method: In this method the same PIN (Personal Identification Number)
 * is entered on the both Wi-Fi Direct devices.
 * \li PBC Method: In which the user simply has to push a button, either
 * an actual or virtual one, on both the Wi-Fi Direct devices.
 *
 * \section p2p_usage Usage
 * In a typical implementation P2P thread is started by calling \ref p2p_start.
 * A valid initialized \ref p2p_config structure needs to be passed to this
 * function. This structure contains a callback handler which is invoked by the
 * P2P thread on occurrence of various events. Once the P2P thread is started,
 * applications can scan for P2P devices or group in the range using \ref
 * p2p_scan. A connection attempt can be made to another p2p device using the
 * pin or pbc method in \ref p2p_connect. If auto_go option is enabled in
 * \ref p2p_config then P2P thread starts as Group Owner, else Group Owner
 * negotiation protocol is performed to determine the Wi-Fi Direct
 * device role (client/AP).
 *
 * On successful P2P session, callback handler is invoked with \ref
 * P2P_SESSION_SUCCESSFUL event with \ref wlan_network structure that contains
 * all the security information for the network with which P2P session was
 * attempted. After this \ref p2p_stop should be called to terminate the P2P
 * thread.
 *
 * \note P2P implementation lets application decide PIN policy. PIN could either
 * be generated by the application, or by the access point or can be statically
 * generated at device manufacturing time. \ref p2p_generate_pin and \ref
 * p2p_validate_pin utility functions can be used by the application to generate
 * and validate PIN.
 *
 * \note P2P thread internally uses multiple dynamic allocations. Please do not
 * reduce the heap size below 64KB if the application wishes to use P2P.
 *
 */

#ifndef P2P_API_H
#define P2P_API_H

#include <wlan.h>

/** P2P log */
#define P2P_LOG(...) wmlog("p2p", ##__VA_ARGS__)

/** Check Bit GO set by peer Bit 0 */
#define P2P_GROUP_OWNER_MASK	0x01
/** Maximum P2P device name length */
#define MAX_DEVICE_NAME_LEN	32

/** enum : P2P session commands */
enum p2p_session_command {
	/** Command to start P2P PIN session */
	CMD_P2P_PIN = 0,
	/** Command to start P2P PBC session */
	CMD_P2P_PBC
};

/** enum : P2P events */
enum p2p_event {
	/** P2P thread started */
	P2P_STARTED = 0,
	/** P2P Auto GO started */
	P2P_AUTO_GO_STARTED,
	/** P2P Device started */
	P2P_DEVICE_STARTED,
	/** P2P Client started */
	P2P_CLIENT_STARTED,
	/** P2P GO started */
	P2P_GO_STARTED,
	/** P2P PBC/PIN Session started */
	P2P_SESSION_STARTED,
	/** P2P PIN checksum failed */
	P2P_SESSION_PIN_CHKSUM_FAILED,
	/** P2P Session aborted */
	P2P_SESSION_ABORTED,
	/** P2P Session registration timeout */
	P2P_SESSION_TIMEOUT,
	/** P2P Session attempt successful */
	P2P_SESSION_SUCCESSFUL,
	/** P2P AP Session attempt successful */
	P2P_AP_SESSION_SUCCESSFUL,
	/** P2P Session failed */
	P2P_SESSION_FAILED,
	/** P2P thread start failed */
	P2P_FAILED,
	/** P2P thread stopped */
	P2P_FINISHED
};

/**
 * This struct is passed to p2p_start(). The user must initialize it
 * with parameters as described inline.
 */
struct p2p_config {
	/** WiFi Direct mode:4 */
	uint8_t role;
	/** Auto Group Owner */
	uint8_t auto_go;
	/** Pin Generator.
	    Wfd Auto Display PIN:3, Wfd Auto Enter PIN:4
	*/
	uint8_t pin_generator;
	/** Version: 0x10: Version 1.0 */
	uint8_t version;
	/** Version: 0x20: Version 2.0 */
	uint8_t version2;
	/** Device name: describes the product */
	uint8_t device_name[32];
	/** Manufacture: identifies the manufacturer of the device */
	uint8_t manufacture[64];
	/** Model name: identifies the model of the device */
	uint8_t model_name[32];
	/** Model number: provides additional description of the device */
	uint8_t model_number[32];
	/** Serial number: identifies the serial number of the
	    Enrollee or Registrar */
	uint8_t serial_number[32];
	/** Configuration Methods:
	  * 0x0001 : USBA
	  * 0x0002 : Ethernet
	  * 0x0004 : Label
	  * 0x0008 : Display
	  * 0x0010 : Ethernet NFC Token
	  * 0x0020 : Integrated NFC Token
	  * 0x0040 : NFC Interface
	  * 0x0080 : Push Button
	  * 0x0100 : Keypad */
	uint16_t config_methods;
	/** Primary Device category: identifies device type category of the
	    Enrollee or Registrar */
	uint16_t primary_dev_category;
	/** Primary Device subcategory: identifies device type subcategory of
	    the Enrollee or Registrar */
	uint16_t primary_dev_subcategory;
	/** RF bands */
	uint8_t rf_bands;
	/** OS Version */
	uint32_t os_version;
	/** P2P message max retry */
	uint8_t p2p_msg_max_retry;
	/** P2P message timeout: Value for Message transmit, timeout
	    unit is msec */
	uint32_t p2p_msg_timeout;
	/** PIN length: Length of the P2P PIN: 8 digits */
	uint16_t pin_len;
	/** P2P callback: Callback function to report events back */
	int (*p2p_callback) (enum p2p_event event, void *data, uint16_t len);
};


/** P2P Device Information to display */
struct p2p_scan_result {
	/** Group capability */
	uint8_t group_capability;
	/** Device Identifier ; Interface address */
	uint8_t device_id[IEEEtypes_ADDRESS_SIZE];
	/** Device Name */
	char device_name[MAX_DEVICE_NAME_LEN + 1];
	/** Device address in deviceInfo */
	uint8_t device_address[IEEEtypes_ADDRESS_SIZE];
	/** P2P GO SSID */
	uint8_t go_ssid[IEEEtypes_SSID_SIZE + 1];
	/** Intended address from Peer */
	uint8_t intended_address[IEEEtypes_ADDRESS_SIZE];
	/** Operating channel */
	int op_channel;
	/** Listen channel */
	int listen_channel;
};

/** Start P2P Service
 *
 * This makes the device discoverable to other devices in the vicinity.
 *
 * \param p2p_conf A pointer to P2P custom configuration structure
 *
 * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
 */
int p2p_start(struct p2p_config *p2p_conf);

/** Stop P2P Service
 *
 * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
 */
int p2p_stop();

/** Scan P2P Devices
 *
 * Fetches the table that has entries for all the P2P devices or groups in the
 * vicinity. It is the responsibility of the application to free this list. One
 * of the entries in this list can be used as a parameter to \ref p2p_connect.
 *
 * \param[out] no number of entries in the array pointed by the return value.
 *
 * \returns Pointer to the result structure.
 */
struct p2p_scan_result *p2p_scan(int *no);

/** Connect to P2P Device
 *
 * Connect to a remote p2p device. This function is typically called whenever
 * the users pushes the p2p button or enters p2p pin.
 *
 * If the device is not a part of any P2P group to begin with the P2P GO
 * negotiation is performed to determine the Group Owner. The caller is notified
 * in the p2p_callback if the device is a group owner or a station.
 *
 * If the device is a group owner, the P2P thread starts the corresponding
 * micro-AP network and the DHCP server on this interface. If the device is a
 * station, the P2P thread establishes the connection with the group owner.
 *
 * \param pbc Set to 1 if Push-button session is desired
 * \param pin Ignore if pbc is 1. If pbc is 0, this indicates the pin that
 * should be used.
 * \param remote The remote device to connect to. If this is set to NULL,
 * session is attempted with the first device.
 *
 * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
 */
int p2p_connect(enum p2p_session_command pbc, uint32_t pin,
			struct p2p_scan_result *remote);

/** Disconnect from P2P Group
 *
 * Disconnect from the current P2P group. If the device is a GO, the entire
 * group is taken down.
 *
 * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
 *
 */
int p2p_disconnect();

/** Generate 8 digit P2P PIN value with random number generator
 *
 * \param p2p_pin Generated 8 digit P2P PIN value
 *
 * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
 */
int p2p_generate_pin(uint32_t *p2p_pin);

/**Validate checksum of PIN
 *
 * \param p2p_pin P2P PIN value
 *
 * \returns WM_SUCCESS if successful, -WM_FAIL otherwise
 **/
int p2p_validate_pin(uint32_t p2p_pin);

#endif
